home *** CD-ROM | disk | FTP | other *** search
- /*
- * Compression routines for the SNOW steganography program.
- * Uses simple Huffman coding.
- *
- * Written by Matthew Kwan - December 1996
- */
-
- #include "snow.h"
-
-
- /*
- * The Huffman codes.
- */
-
- static const char *huffcodes[256] = {
- #include "huffcode.h"
- };
-
-
- /*
- * Local variables used for compression.
- */
-
- static int compress_bit_count;
- static int compress_value;
- static int compress_bits_in;
- static int compress_bits_out;
-
-
- /*
- * Initialize the compression routines.
- */
-
- void
- compress_init (void)
- {
- compress_bit_count = 0;
- compress_value = 0;
- compress_bits_in = 0;
- compress_bits_out = 0;
-
- encrypt_init ();
- }
-
-
- /*
- * Compress a single bit.
- */
-
- BOOL
- compress_bit (
- int bit,
- FILE *inf,
- FILE *outf
- ) {
- if (!compress_flag)
- return (encrypt_bit (bit, inf, outf));
-
- compress_bits_in++;
- compress_value = (compress_value << 1) | bit;
-
- if (++compress_bit_count == 8) {
- const char *s;
-
- for (s = huffcodes[compress_value]; *s != '\0'; s++) {
- int bit;
-
- if (*s == '1')
- bit = 1;
- else if (*s == '0')
- bit = 0;
- else {
- fprintf (stderr, "Illegal Huffman character '%c'\n", *s);
- return (FALSE);
- }
-
- if (!encrypt_bit (bit, inf, outf))
- return (FALSE);
- compress_bits_out++;
- }
-
- compress_value = 0;
- compress_bit_count = 0;
- }
-
- return (TRUE);
- }
-
-
- /*
- * Flush the contents of the compression routines.
- */
-
- BOOL
- compress_flush (
- FILE *inf,
- FILE *outf
- ) {
- if (compress_bit_count != 0 && !quiet_flag)
- fprintf (stderr, "Warning: residual of %d bits not compressed\n",
- compress_bit_count);
-
- if (compress_bits_out > 0 && !quiet_flag) {
- double cpc = (double) (compress_bits_in - compress_bits_out)
- / (double) compress_bits_in * 100.0;
-
- if (cpc < 0.0)
- fprintf (stderr,
- "Compression enlarged data by %.2f%% - recommend not using compression\n",
- -cpc);
- else
- fprintf (stderr, "Compressed by %.2f%%\n", cpc);
- }
-
- return (encrypt_flush (inf, outf));
- }
-
-
- /*
- * Local variables used for output.
- */
-
- static int output_bit_count;
- static int output_value;
-
-
- /*
- * Initialize the output variables.
- */
-
- static void
- output_init (void)
- {
- output_bit_count = 0;
- output_value = 0;
- }
-
-
- /*
- * Output a single bit.
- */
-
- static BOOL
- output_bit (
- int bit,
- FILE *outf
- ) {
- output_value = (output_value << 1) | bit;
-
- if (++output_bit_count == 8) {
- if (fputc (output_value, outf) == EOF) {
- perror ("Output file");
- return (FALSE);
- }
-
- output_value = 0;
- output_bit_count = 0;
- }
-
- return (TRUE);
- }
-
-
- /*
- * Flush the contents of the output routines.
- */
-
- static BOOL
- output_flush (
- FILE *outf
- ) {
- if (output_bit_count > 2 && !quiet_flag)
- fprintf (stderr, "Warning: residual of %d bits not output\n",
- output_bit_count);
-
- return (TRUE);
- }
-
-
- /*
- * Local variables used for uncompression.
- */
-
- static int uncompress_bit_count;
- static char uncompress_value[256];
-
-
- /*
- * Initialize the uncompression routines.
- */
-
- void
- uncompress_init (void)
- {
- uncompress_bit_count = 0;
-
- output_init ();
- }
-
-
- /*
- * Find the Huffman code string that matches.
- */
-
- static int
- huffcode_find (
- const char *str
- ) {
- int i;
-
- for (i=0; i<256; i++)
- if (strcmp (str, huffcodes[i]) == 0)
- return (i);
-
- return (-1);
- }
-
-
- /*
- * Uncompress a single bit.
- */
-
- BOOL
- uncompress_bit (
- int bit,
- FILE *outf
- ) {
- int code;
-
- if (!compress_flag)
- return (output_bit (bit, outf));
-
- uncompress_value[uncompress_bit_count++] = bit ? '1' : '0';
- uncompress_value[uncompress_bit_count] = '\0';
-
- if ((code = huffcode_find (uncompress_value)) >= 0) {
- int i;
-
- for (i=0; i<8; i++) {
- int b = ((code & (128 >> i)) != 0) ? 1 : 0;
-
- if (!output_bit (b, outf))
- return (FALSE);
- }
-
- uncompress_bit_count = 0;
- }
-
- if (uncompress_bit_count >= 255) {
- fprintf (stderr, "Error: Huffman uncompress buffer overflow\n");
- return (FALSE);
- }
-
- return (TRUE);
- }
-
-
- /*
- * Flush the contents of the uncompression routines.
- */
-
- BOOL
- uncompress_flush (
- FILE *outf
- ) {
- if (uncompress_bit_count > 2 && !quiet_flag)
- fprintf (stderr, "Warning: residual of %d bits not uncompressed\n",
- uncompress_bit_count);
-
- return (output_flush (outf));
- }
-